Blinkt!でみる*BSDのGPIO: または、翼よあれがaarch64の灯だ
https://gyazo.com/f5abd954c71bb4eee7c41f21d4885b86
はじめに
ここでは、64bit ARMを使った各種ボードのNetBSD(とFreeBSD)で、Blinkt!と呼ばれる8連LEDを使う方法について説明します。
参考文献
Blinkt!ってなあに?
Blinkt!は、Raspberry Piの40ピンGPIOに刺してつかえる、8連のフルカラーLEDです。
2つのGPIOだけを使って、フルカラーLEDの操作が可能です。
https://gyazo.com/c2d0b9273f0977a33beba637edcd7370
Blinkt!=ラズベリーパイ40pin GPIO用8連フルカラーLED(APA102)
販売
table:PIN配置
役割 RPIピン番号 RPI BCM
DATA 16 23
CLOCK 18 24
Vcc(5V) 4 -
GND 6 -
GPIO 23と24だけで、フルカラーLED 8つを制御する
Blinkt!の制御信号
Blinkt!で使われる2つのGPIOは、DATA(16pin)とCLOCK(18pin)で、それぞれLEDに送るデータと、データを送るタイミングを指定するクロックになります。
クロック(青)の立ち下がりのデータ(オレンジ)の値を送ることになっています。
以下の順で1つのLEDあたり8bit x 4のデータを送信
blightness(有効5bit/8bit)
b
g
r
https://gyazo.com/ebb3b30d0bd5eedaa1cda52c04421fc0
Raspbian用Blinkt!ライブラリの構成
これは、RPi.GPIO pythonライブラリを使って、Blinkt!を操作するための機能を提供します。
table: Blinkt!ライブラリ階層
記述言語
アプリケーション python
blinkt.py Blinkt!用のpythonライブラリ
RPi.GPIO Raspberry PiでGPIOを使うための、C言語で記述されたpythonライブラリ
OS GPIO layer C言語やユーザランドコマンドで実装する
*BSDのGPIOを使って実装する時は、RPi.GPIO相当のものを作れば、アプリケーションやblinkt.pyは変更無しでそのまま使うことができます。
*BSD GPIO ユーザランドコマンド
*BSDでは、GPIOを操作するためのユーザランドコマンドgpioctlが提供されています。
設定は/etc/gpio.confで行え、ピンに名前をつけることも可能です。
table:各BSDのユーザランドコマンド
FreeBSD NetBSD/OpenBSD
コマンド gpioctl(1,8) gpioctl(8)
デバイス指定 -f /dev/gpioc0 gpio0 (or /dev/gpio0)
初期化(出力モード) -c <pin> OUT set out {pin} pin_name (*1) 入力 <pin> <pin>
pin名を設定する -n {pin} pin_name set <mode> {pin} pin_name
<pin>は、整数のピン番号もしくは文字列のピン名、{pin}はピン番号。
*1. 後述のとおり、NetBSDとOpenBSDでは、/etc/gpio.confの設定に基づいて、起動時のみ初期化ができる。
NetBSD/OpenBSDでのGPIO利用時の注意事項(GPIOの初期化)
NetBSD/OpenBSDで、GPIOを利用する時は、以下の点に注意してください。
GPIOの設定は、securelevel<=0 の時にしか変えられない
→ブート終了後は、GPIO設定は変えられない
ただし、options INSECUREを指定して作ったカーネルでは変更できる
起動時に初期設定を行うには、/etc/rc.confと/etc/gpio.confに以下のような設定を行う
code:/etc/rc.conf
gpio=YES
code:/etc/gpio.conf
# GPIO setting for Blinkt! (pin 23 and 24)
gpio0 23 set out dat
gpio0 24 set out clk
gpio0 25 set in sw
*BSD GPIO C言語プログラムインタフェース
*BSDでは、C言語でGPIOを操作するためのAPIが提供されています。
しかし、FreeBSDとNetBSD/OpenBSDでは、APIが異なっています。
以下にAPIの概要を示します。
table:*BSDのC言語API
FreeBSD NetBSD/OpenBSD
header sys/types.h, libgpio.h sys/types.h, sys/gpio.h, sys/ioctl.h
library -lgpio
init gpio_open(0) open("/dev/gpio0",O_RDWR)
setup gpio_pin_set_flags(handle,config) ioctl(fd,GPIOSET,gpio_set)
output gpio_pin_set(handle,pin,value) ioctl(fd,GPIOWRITE,gpio_req)
input gpio_pin_input(handle,pin) ioctl(fd,GPIOREAD,gpio_req)
GPIOを使うデバイスをinitで指定し、GPIOの設定をsetupでおこないます。
GPIOでの入出力時には、入力にはinputを、出力にはoutputを使います。
で、とりあえず*BSDでBlinkt!だけ動くRPi.GPIOをでっち上げてみました
*BSD(正確にはNetBSDとFreeBSD)で、C言語APIを使ってRPi.GPIOでBlinkt!が動作する最低限のライブラリを作成しました。
FreeBSDとNetBSDの両対応になってます (OpenBSDは試してません)
Raspberry Pi 以外のボードでは、GPIOのポートに従って、blinkt.pyやGPIO.cをいじる必要があります(後述)
Raspberry Pi以外のボードで使う例
ここでは、Raspberry Pi以外のボードで、Blinkt!を使う場合の例を紹介します。
GPIOピン番号はむとうが接続した例になっていますので、適宜自分が接続したピンに対応する番号に変更してください。
ここでは、以下のボードについて、説明を行います。
NanoPi NEO2
Jetson TX1
NanoPi NEO2 de Blinkt!
https://gyazo.com/0983498f9e933eff264f8d60d1750b24
使っているGPIOポートの番号が違うので、使っているものに変更します。
table:NanoPi NEO2 pin
NanoPi NEO2でのピン表示 NetBSD GPIOデバイス NetBSDピン番号
DATA GPIO1-5 gpio0 11
CLK GPIO1-11 gpio0 0
code:blinkt.py.patch
--- blinkt.py.org 2018-10-18 16:47:27.732733560 +0900
+++ blinkt.py 2018-10-23 14:12:37.499090099 +0900
@@ -2,13 +2,13 @@
import atexit
import time
-import RPi.GPIO as GPIO
+import GPIO as GPIO
__version__ = '0.1.2'
-DAT = 23
-CLK = 24
+DAT = 11
+CLK = 0
NUM_PIXELS = 8
BRIGHTNESS = 7
Jetson TX1 de Blinkt!
https://gyazo.com/3a593d49eafb1c3d42e6e2f48ac7c5cc
NVIDIA Jetson TX1は、NVIDIAが提供しているGPUが使えるARMボードです。
割り当てるGPIOポートのGPIOデバイスが違うので変更します。
table:Jetson TX1 pin
Jetson TX1 J21ピン番号 NetBSD GPIOデバイス NetBSDピン番号
DATA 16 gpio4 5
CLK 13 gpio4 6
code:GPIO.c.patch
--- GPIO.c.org 2018-10-30 00:53:20.690389084 +0000
+++ GPIO.c 2018-10-27 06:52:45.558201090 +0000
@@ -25,7 +25,7 @@
gpio_handle_t gpio_handle=(gpio_handle_t)NULL;
-#define DEV "/dev/gpio0"
+#define DEV "/dev/gpio4"
int fd;
code:blinkt.py.patch
--- ../library/blinkt.py 2018-10-27 06:47:04.978619602 +0000
+++ blinkt.py 2018-10-27 08:06:22.269554853 +0000
@@ -2,13 +2,13 @@
import atexit
import time
-import RPi.GPIO as GPIO
+import GPIO as GPIO
__version__ = '0.1.2'
-DAT = 23
-CLK = 24
+DAT = 5
+CLK = 6
NUM_PIXELS = 8
BRIGHTNESS = 7
おわりに
とりあえず、aarch64のご贈答箱全部を光らせることができました
NetBSD on Jetson TX1
NetBSD on NanoPi NEO2
(FreeBSD on Raspberry Pi 3B+)
物理的なGPIOと、OSでのGPIOデバイスピン番号の対応を探すのは大変です
危険なポートもありますorz
Jetson TX1の power button, network interface(cdce0), SD(sdhc0)は、GPIOに繋がっている
みなさんもピカピカしてみませんか?